import java.awt.Container;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JFrame;

/**
 * This Class allows the dragging and dropping of a JFrame, and in Tasky
 * context, it is the JFrame used in the BaseWindow class. Objects which
 * are attached with this Listener will cause the BaseWindow JFrame to 
 * drag and drop whenever a mouse clicks and drag on that object
 * 
 * @author Keith Lim Yong Ming A0097846J
 *
 */

public class MoveMouseListener implements MouseListener, MouseMotionListener {
	JFrame target;
	Point start_drag;
	Point start_loc;

	private static final float DEFAULT_OPACITY = 0.5f;
	
	public MoveMouseListener(JFrame baseFrame) {
		this.target = baseFrame;
	}

	public JFrame getFrame(Container target) {
		if (targetIsJFrame(target)) {
			return (JFrame) target;
		}
		return getFrame(target.getParent());
	}

	private boolean targetIsJFrame(Container target) {
		return target instanceof JFrame;
	}

	Point getScreenLocation(MouseEvent e) {
		Point cursor = e.getPoint();
		Point target_location = this.target.getLocationOnScreen();
		return prepareMouseLocation(cursor, target_location);
	}

	private Point prepareMouseLocation(Point cursor, Point target_location) {
		return new Point((int) (target_location.getX() + cursor.getX()),
				(int) (target_location.getY() + cursor.getY()));
	}

	public void mouseClicked(MouseEvent e) {
	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	public void mousePressed(MouseEvent e) {
		this.start_drag = this.getScreenLocation(e);
		this.start_loc = this.getFrame(this.target).getLocation();
	}

	public void mouseReleased(MouseEvent e) {
		target.setOpacity(1);
	}

	public void mouseDragged(MouseEvent e) {
		target.setOpacity(DEFAULT_OPACITY);

		Point current = this.getScreenLocation(e);
		Point offset = prepareOffSetPoint(current);
		
		JFrame frame = this.getFrame(target);
		Point new_location = prepareNewLocPoint(offset);
		
		frame.setLocation(new_location);
	}

	private Point prepareNewLocPoint(Point offset) {
		return new Point(
				(int) (this.start_loc.getX() + offset.getX()),
				(int) (this.start_loc.getY() + offset.getY()));
	}

	private Point prepareOffSetPoint(Point current) {
		return new Point(
				(int) current.getX() - (int) start_drag.getX(),
				(int) current.getY() - (int) start_drag.getY());
	}

	public void mouseMoved(MouseEvent e) {
	}
}
